export const CLIENT_TYPE = clientType();

/**
 * 获取对象类型
 * @public
 * @param {Object} obj
 * @returns {String} type
 */
export function isType(obj) {
  if (obj instanceof Element) {
    return 'Element';
  }

  return /\b((?!object)\w)+\b/.exec(Object.prototype.toString.call(obj))[0];
}

/**
 * 是否空对象
 * @param {any} value 判断对象
 * @returns {Boolean}
 */
export function isEmpty(value) {
  if (!value) return true;
  let type = isType(value);
  if (type === 'Object') return !Object.keys(value).length;
  if (type === 'Array') return !value.length;
  if (type === 'Number') return !(value > 0 && value < Number.POSITIVE_INFINITY);
  if (type === 'String') {
    return ['false', 'undefined', 'null', 'NaN', '-Infinity', 'Infinity', '{}', '[]'].some(
      (item) => {
        return value === item;
      }
    );
  }
  return !value;
}

/**
 * 对象序列化为url参数
 * @public
 * @param {Object} obj
 * @returns {String} 序列化后的字符串
 */
export function serializeToUrl(obj) {
  let params = [];
  let keys = Object.keys(obj);
  for (let i = 0; i < keys.length; i++) {
    if (obj[keys[i]] === undefined || obj[keys[i]] === null) continue;
    let key = keys[i];
    let val = encodeURIComponent(obj[keys[i]]);
    params.push(`${key}=${val}`);
  }
  return params.join('&');
}

/**
 * a=b&b=d 转换成对象类型
 * @private
 * @param {String} search  a=b&b=d
 * @returns {Object} {{}}
 */
function searchToObj(search) {
  if (isEmpty(search) || isType(search) !== 'String') return {};

  let searchArr = search.split('&');
  let params = {};
  for (let i = 0; i < searchArr.length; i++) {
    let pair = searchArr[i].split('=');
    if (pair[1] === 'undefined') continue;
    params[pair[0]] = decodeURIComponent(pair[1] || '');
  }
  return params;
}

/**
 * 获取url参数集
 * @public
 * @param {String?} [url = window.location.href]
 * @param {Boolean?} [includeHash = true] 是否包含hash
 * @returns {({} & {}) | {}}
 */
export function getUrlParams(url, includeHash) {
  if (arguments.length === 1 && isType(arguments[0]) !== 'String') {
    includeHash = !!arguments[0];
  }
  url = isType(url) === 'String' ? url : window.location.href;
  includeHash = isType(includeHash) === 'Boolean' ? includeHash : true;

  let searchUrl = url;
  let isSearch = '';
  let searchObj = '';
  let isHash = url.indexOf('#');

  isHash > -1 && (searchUrl = url.slice(0, isHash));
  isSearch = searchUrl.indexOf('?');
  isSearch > -1 && (searchObj = searchUrl.slice(isSearch + 1));

  searchObj = searchToObj(searchObj);

  if (!includeHash || isHash === -1) return searchObj;

  let hashObj = '';
  let hashUrl = url.slice(isHash);
  let isHashSearch = hashUrl.indexOf('?');
  isHashSearch > -1 && (hashObj = hashUrl.slice(isHashSearch + 1));

  hashObj = searchToObj(hashObj);

  return Object.assign({}, searchObj, hashObj);
}

/**
 * 获取url路径参数
 * - 注意：如果vueRouter使用的是History模式也会被解析成参数
 * @param {string?} [url = window.location.url]
 * @param url
 * @return {any[]|string[]}
 */
export function getUrlPathParams(url) {
  if (isType(url) !== 'String') {
    url = window.location.href;
  }

  const urlReg = /(^https?):\/\/([0-9a-z.]*)(:\d*)?([/0-9a-zA-Z-_.]*)?(\?[0-9a-zA-Z&-_=]*)?(#.*)?/;
  const urlMatch = url.match(urlReg);

  if (!urlMatch || isEmpty(urlMatch[4])) return [];

  return urlMatch[4].split('/').filter((item) => {
    if (isEmpty(item)) return false;
    return !/^\w+\.\w+$/.test(item);
  });
}

/**
 * 加密文本内容
 * @param {String} text 必填，需加密的文本内容
 * @param {String} [symbol = '*'] 可选，加密的符号
 * @param {Array} [ignore = []] 可选，忽略加密文本
 * @param {Function?} callback 可选，回调函数。返回true加密，false不加密
 * @returns {string|*} 加密后的文本
 */
// export function encryptText(text, symbol, ignore, callback) {
//   if (isEmpty(text) || isType(text) !== 'String') return '';
//   symbol = '*';
//   ignore = [];
//   callback = (value, index, text) => index !== 0;
//   for (let i = 1; i <= 3; i++) {
//     if (arguments[i] === undefined) break;
//     let argType = isType(arguments[i]);
//     switch (argType) {
//       case 'String':
//         symbol = arguments[i];
//         break;
//       case 'Array':
//         ignore = arguments[i];
//         break;
//       case 'Function':
//         callback = arguments[i];
//         break;
//     }
//   }

//   if (ignore.includes(text)) return text;

//   let encrypt = '';
//   for (let i = 0; i < text.length; i++) {
//     encrypt += callback(text[i], i, text) ? symbol : text[i];
//   }

//   return encrypt;
// }

/**
 * 是否外部地址
 * @param {string} path
 * @returns {Boolean}
 */
export function isExternalUrl(path) {
  return /^(https?:|mailto:|tel:)/.test(path);
}

/**
 * 判断客户端类型
 * - wx: 微信
 * - ding: 钉钉
 * - cx: 超星学习通
 * - other: 其他
 * @return {string}
 */
export function clientType() {
  const ua = window.navigator.userAgent.toLowerCase();

  // 微信
  if (/micromessenger/.test(ua)) {
    return 'wx';
  }
  // 钉钉
  else if (/dingtalk/.test(ua)) {
    return 'ding';
  }
  // 超星
  else if (/chaoxingstudy/.test(ua)) {
    return 'cx';
  }

  return 'other';
}

// ---------------------------------------------之前项目使用-----------------------------------------

/**
 *获取url参数的值
 * @param {string} paramKey
 * @returns {string}
 */
export function getUrlParamByKey(paramKey) {
  // 参数正则
  let reg = new RegExp('(^|&)' + paramKey + '=([^&/]*)(&|/|$)', 'i');
  // 匹配参数
  let result =
    window.location.search.substr(1).match(reg) ||
    (window.location.hash.split('?')[1] && window.location.hash.split('?')[1].match(reg));

  return result ? decodeURIComponent(result[2]) : null;
}

/**
 * 转换对象的key
 * @param {Array|Object} data
 * @param {Object} target
 */
export function objKeyTransform(data, target) {
  var type = isType(data);
  if (type !== 'Array' && type !== 'Object') return data;
  if (isEmpty(data) || isEmpty(target)) return data;
  if (type === 'Object') data = [data];

  var targetKeys = Object.keys(target);
  var newData = [];

  for (var i = 0; i < data.length; i++) {
    var dataItem = Object.assign(data[i]);
    var newItem = {};
    for (var key in dataItem) {
      targetKeys.indexOf(key) > -1
        ? (newItem[target[key]] = dataItem[key])
        : (newItem[key] = dataItem[key]);
    }
    newData.push(newItem);
  }

  return type === 'Object' ? newData[0] : newData;
}
